package com.system.boss.openssl.controller;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.Date;
import java.util.List;

import org.apache.commons.io.IOUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.system.boss.openssl.dto.SysOpensslAddReq;
import com.system.boss.openssl.enums.SysOpensslCerStatusEnum;
import com.system.boss.openssl.model.SysOpenssl;
import com.system.boss.openssl.service.OpenSSLService;
import com.system.core.controller.ControllerBase;
import com.system.core.results.ResultBase;
import com.system.core.view.layui.table.TableViewReqDto;
import com.system.core.view.layui.table.TableViewRspDto;
import com.system.core.view.layui.tree.TreeNode;

import io.swagger.v3.oas.annotations.Hidden;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotBlank;


@Controller
@RequestMapping("boss/openssl")
@Hidden
public class OpenSSLController extends ControllerBase {
	
	@Autowired
	private OpenSSLService openSSLService;
	
	@RequestMapping(value = "revokecert",method = RequestMethod.POST)
	@ResponseBody
	public ResultBase revokeCert(Long caid , Long cerid) {
		return openSSLService.revokeCer(caid, cerid);
	}
	
 	@RequestMapping(value = "usercert-tableview-data",method = RequestMethod.POST)
	@ResponseBody
	public TableViewRspDto<SysOpenssl> userCertList(TableViewReqDto page,SysOpenssl filter){
		return openSSLService.userCertList(page, filter);
	}
	
	@RequestMapping(value = "usercert-add",method = RequestMethod.POST)
	@ResponseBody
	public ResultBase userCertAdd(@Validated SysOpensslAddReq sysOpensslAddReq) throws Exception {
		
		SysOpenssl sysOpenssl = new SysOpenssl();
		
		BeanUtils.copyProperties(sysOpensslAddReq, sysOpenssl);
		
		sysOpenssl.setResourceId(sysOpensslAddReq.getCommonName()+"-group");
		sysOpenssl.setIssueTime(new Date());
		sysOpenssl.setCerStatus(SysOpensslCerStatusEnum.NORMAL);
		sysOpenssl.setCerPid(sysOpenssl.getCerPid()==null?0:sysOpenssl.getCerPid());
		return openSSLService.userCertAdd(sysOpenssl);
	}
	
	@RequestMapping(value = "usercert-get",method = RequestMethod.POST)
	@ResponseBody
	public SysOpenssl userCertGet(SysOpenssl sysOpenssl) {
		return openSSLService.userCertGet(sysOpenssl);
	}
	
	@RequestMapping(value = "usercert-delete",method = RequestMethod.POST)
	@ResponseBody
	public ResultBase userCertDeletee(SysOpenssl sysOpenssl) {
		SysOpenssl willBeDelete = openSSLService.userCertGet(sysOpenssl);
		fileDelete(willBeDelete.getWorkDir()+willBeDelete.getCerPath());
		fileDelete(willBeDelete.getWorkDir()+willBeDelete.getKeyPath());
		fileDelete(willBeDelete.getWorkDir()+willBeDelete.getKeyWithoutPasswdPath());
		fileDelete(willBeDelete.getWorkDir()+willBeDelete.getP12Path());
		
		int deleted = openSSLService.userCertDelete(sysOpenssl);
		if(deleted > 0) {
			return new ResultBase(true, "删除成功");
		} else {
			return new ResultBase("啥都没删除，删了个寂寞~！");
		}
	}
	
	@RequestMapping(value = "tree-data-source",method = RequestMethod.POST)
	@ResponseBody
	public List<TreeNode> treeDataSourceBind(){
		return openSSLService.getNodeByParentId(0L);
	}
	
	@RequestMapping(value = "nginx-config-download",method = RequestMethod.GET)
	public void nginxCerDownload(Long cerid,HttpServletResponse response) {
		
		response.setCharacterEncoding("utf-8");
		response.setHeader("Content-Disposition", "attchement;filename=nginx.zip");
		response.setContentType("multipart/form-data");
		
		try {
			openSSLService.nginxCerDownload(cerid, response.getOutputStream());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@RequestMapping(value = "crl-download",method = RequestMethod.GET)
	public void crlCertDownload(HttpServletResponse response,@NotBlank(message = "请选择CA") Long cerId) throws Exception {
		
		File crl = openSSLService.makeCrl(cerId);
		
		response.setContentType("application/force-download");
		response.setHeader("Content-Disposition", "attachment;fileName=revoke.crl");
			
		BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
		
		IOUtils.copy(new FileInputStream(crl), bos);
		
		bos.flush();
		bos.close();
	}
	
	@RequestMapping(value = "usercert-download",method = RequestMethod.GET)
	public void userCertDownload(HttpServletResponse response,SysOpenssl usercert,String downloadType) throws Exception {
		
		SysOpenssl cert = openSSLService.getCertById(usercert.getCerId());
		
		File file;
		
		switch(downloadType) {
			case "user_cer":
				file = new File(cert.getWorkDir(),cert.getCerPath());
				
				response.setContentType("application/x-x509-ca-cert");
				response.setHeader("Content-Disposition", "attachment;fileName="+cert.getCommonName()+".crt");
				break;
			case "key_cer":
				file = new File(cert.getWorkDir(),cert.getKeyPath());
				
				response.setContentType("application/force-download");
				response.setHeader("Content-Disposition", "attachment;fileName="+cert.getCommonName()+".pem");
				break;
			case "key_cer_nopasswd":
				file = new File(cert.getWorkDir(),cert.getKeyWithoutPasswdPath());
				
				response.setContentType("application/force-download");
				response.setHeader("Content-Disposition", "attachment;fileName="+cert.getCommonName()+"_nopasswd.pem");
				break;
			case "pkcs12":
				file = new File(cert.getWorkDir(),cert.getP12Path());
				
				response.setContentType("application/force-download");
				response.setHeader("Content-Disposition", "attachment;fileName="+cert.getCommonName()+".p12");
				break;
			default:
				return;
		}
		
		response.setContentLengthLong(file.length());
		BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
		IOUtils.copy(new FileInputStream(file), bos);
		
		bos.flush();
		bos.close();
	}
	
	@RequestMapping(value = "to_page",method = RequestMethod.GET)
	public String toPage() {
		return "/boss/openssl/openssl-list";
	}
	
	private boolean fileDelete(String filePath) {
		File file = new File(filePath);
		if(file.exists()) {
			return file.delete();
		} else {
			return false;
		}
	}
}